package au.com.iglootech.TaxTimeToolTip.ui.invoice;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import au.com.iglootech.TaxTimeToolTip.Entity.Task;
import au.com.iglootech.TaxTimeToolTip.service.InvoiceNumberService;
import au.com.iglootech.TaxTimeToolTip.service.InvoiceTaxService;
import au.com.iglootech.TaxTimeToolTip.util.FeeUtil;
import au.com.iglootech.TaxTimeToolTip.util.InvoiceUtil;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.vaadin.Application;
import com.vaadin.terminal.StreamResource;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

@Configurable(preConstruction = true)
@Component
@Scope("request")
public class PerviewWindow extends Window {
	/**
	 * 
	 */
	private static final long serialVersionUID = 8067523851039436765L;
	private static final String ADDRESS = "AddressText";
	private static final String DETAILS = "Details";
	private static final String INVOICE_NUMBER = "InvoiceNumber";
	private static final String INVOICE_DATE = "InvoiceDate";
	private static final String PAGE = "page";
	private static final String YOUR_REF = "YourRef";
	private static final String TERMS = "Terms";
	private static final String TOTAL_GST = "TotalGST";
	private static final String DELIVERY_ADDRESS = "DeliveryAddress";
	private static final String SUB_TOTAL = "SubTotal";
	private static final String EX_GST = "ExGST";
	private static final String GST = "GST";
	private static final String INC_GST = "IncGST";
	private static final String PAID_DATE = "PaidDATE";
	private static final String BANLANCE_DUE = "BalanceDue";

	private InvoiceDateVO invoiceDateVO;
	private List<Task> tasks;
	private DoAction action;
	@Autowired
	private transient InvoiceNumberService invoiceNumberService;
	@Autowired
	private transient InvoiceTaxService invoiceTaxService;

	public interface DoAction extends Serializable {
		public void afterInvoice();
	}

	public PerviewWindow(final Application application,
			final InvoiceDateVO invoiceDateVO, final List<Task> tasks,
			DoAction action) {
		super();
		this.invoiceDateVO = invoiceDateVO;
		this.tasks = tasks;
		this.action = action;
		// generate invoice number
		final Integer invoiceNumber = invoiceNumberService.getNextNumber();
		invoiceDateVO.setInvoiceNumber(InvoiceUtil
				.formatInvoiceNumber(invoiceNumber));
		((VerticalLayout) getContent()).setSizeFull();
		setResizable(true);
		setWidth("800px");
		setHeight("600px");
		setModal(true);
		// button bar
		HorizontalLayout buttonBar = new HorizontalLayout();
		buttonBar.setSpacing(true);
		Button confirmButton = new Button("Confirm");
		confirmButton.addListener(new Button.ClickListener() {
			@Override
			public void buttonClick(ClickEvent arg0) {
				invoiceTaxService.invoiceTax(tasks, invoiceNumber, invoiceDateVO);
				getWindow().showNotification("Invoices have been generated.");
				PerviewWindow.this.close();
				PerviewWindow.this.action.afterInvoice();
			}
		});
		buttonBar.addComponent(confirmButton);
		Button cancelButton = new Button("Cancel");
		cancelButton.addListener(new Button.ClickListener() {

			@Override
			public void buttonClick(ClickEvent arg0) {
				PerviewWindow.this.close();
			}
		});
		buttonBar.addComponent(cancelButton);
		// p.addComponent(buttonBar);
		// pdf component
		StreamResource.StreamSource ss = new StreamResource.StreamSource() {

			@Override
			public InputStream getStream() {
				InputStream is = PerviewWindow.class.getClassLoader()
						.getResourceAsStream("template/invoice_template.pdf");
				ByteArrayOutputStream os = new ByteArrayOutputStream();
				try {
					PdfReader pdfTemplate = new PdfReader(is);
					PdfStamper stamper = new PdfStamper(pdfTemplate, os);
					AcroFields form = stamper.getAcroFields();
					fillUpFields(form);
					stamper.setFormFlattening(true);
					stamper.close();
					pdfTemplate.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (DocumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return new ByteArrayInputStream(os.toByteArray());

			}
		};
		Embedded e = new Embedded("Invoice Preview", new StreamResource(ss,
				"file.pdf", application));
		e.setSizeFull();
		e.setType(Embedded.TYPE_BROWSER);
		e.setMimeType("application/pdf");
		VerticalLayout pdfLayout = new VerticalLayout();
		pdfLayout.setHeight("500px");
		pdfLayout.addComponent(e);
		addComponent(pdfLayout);
		addComponent(buttonBar);

	}

	public void fillUpFields(AcroFields form) throws IOException,
			DocumentException {

		form.setField(ADDRESS, invoiceDateVO.contactName + "\n"
				+ invoiceDateVO.address1);
		form.setField(DETAILS, invoiceDateVO.getDetails());
		form.setField(GST, invoiceDateVO.getGst());
		form.setField(INVOICE_NUMBER, invoiceDateVO.getInvoiceNumber());
		form.setField(INVOICE_DATE, invoiceDateVO.getInvoiceDate());
		form.setField(PAGE, "1");

		form.setField(YOUR_REF, invoiceDateVO.getYourRef());
		form.setField(TERMS, invoiceDateVO.getTerms());
		form.setField(TOTAL_GST,
				FeeUtil.formatFeeWithUnit(invoiceDateVO.getTotalGST()));
		form.setField(SUB_TOTAL, invoiceDateVO.getSubTotal());
		form.setField(INC_GST, invoiceDateVO.getIncGST());
		form.setField(PAID_DATE, invoiceDateVO.getInvoiceDate());
		form.setField(BANLANCE_DUE, invoiceDateVO.getBalanceDue());

	}

	public DoAction getAction() {
		return action;
	}

	public void setAction(DoAction action) {
		this.action = action;
	}
}
